package unit01;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * @author wangzhuangzhuang
 * @DESC: 构造函数引用
 * @date 2022-05-02 23:41
 */
public class ConstructorFunctionReferenceDemo {

	public static void main(String[] args) {
//		listToStreamAndStreamToList();
		varargsConstructorMethod();
	}

	public static void personListToNameList() {
		Person felix = new Person("Felix");
		Person damon = new Person("Damon");
		Person amy = new Person("Amy");
		List<Person> personData = new ArrayList<Person>(Arrays.asList(felix, damon, amy));
		// First Style
		List<String> personNames01 = personData.stream()
				.map(p -> p.getName()) // 使用Lambda表达式来调用构造函数
				.collect(Collectors.toList());
		// Second Style
		List<String> personNames02 = personData.stream()
				.map(Person::getName) // 使用构造函数引用来实例化Person
				.collect(Collectors.toList());
		/**
		 * Person::new的作用是引用Person类中的构造函数。
		 * */
	}

	/*
	 * Person{name='Wangzz'}
	 * Person{name='Wangyt'}
	 * Person{name='Ada Lovelace'}
	 * Person{name='Barbara Liskov'}
	 * Person{name='Wangzz'}
	 * Person{name='Wangyt'}
	 * Person{name='Ada Lovelace'}
	 * Person{name='Barbara Liskov'}
	 * */
	public static void nameListToPersonList() {
		List<String> names = Arrays.asList("Wangzz", "Wangyt", "Ada Lovelace", "Barbara Liskov");

		List<Person> peoples01 = names.stream()
				.map(name -> new Person(name)) // 通过Lambda表达式来调用构造函数
				.collect(Collectors.toList());
		peoples01.forEach(System.out::println);

		List<Person> peoples02 = names.stream()
				.map(Person::new)// 通过方法引用来调用构造函数
				.collect(Collectors.toList());
		peoples02.forEach(System.out::println);

	}

	/**
	 * 列表与流之间对象的转换并不会导致引用的变化, 但是当调用map(Person::new)时就会重新调用一个方法
	 * */
	public static void listToStreamAndStreamToList() {
		Person before = new Person("Grace Hopper");
		List<Person> people = Stream.of(before)
				.collect(Collectors.toList());
		Person after = people.get(0);
		System.out.println(after == before); // true
		before.setName("Grace Murray Hopper");
		System.out.println("Grace Murray Hopper".equals(after.getName())); // true
		// =======================================================================
		List<Person> people1 = Stream.of(before)
				.map(Person::new) // 通过调用构造函数可以将流代码从原始实例中分离出来 ★
				.collect(Collectors.toList());

		after = people1.get(0);
		System.out.println(before == after); // false
		before.setName("Rear　Admiral Dr.");
		System.out.println(before.getName().equals(after.getName())); // false
	}

	public static void varargsConstructorMethod(){
		List<Person> persons = Arrays.asList("felix wangzz amy").stream()
				.map(name -> name.split(" "))
				.map(Person::new)
				.collect(Collectors.toList());
		persons.forEach(System.out::println);
	}


}

class Person {
	private String name;

	public Person() {
	}

	public Person(String name) {
		this.name = name;
	}

	// 复制构造函数（copy constructor) 传入一个Person参数，并返回一个具有相同特性的新Person
	public Person(Person person) {
		this.name = person.name;
	}

	// 可变参数构造函数（varargs constructor）
	public Person(String ...names) {
		this.name = Arrays.stream(names)
				.collect(Collectors.joining(" "));
	}


	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	@Override
	public String toString() {
		return "Person{" +
				"name='" + name + '\'' +
				'}';
	}
}